package com.easydict.spi;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 字典解析上下文
 * 封装字典解析过程中的所有必要信息
 */
public class DictionaryResolutionContext {
    
    private final String typeCode;
    private final Object rawValue;
    private final String stringValue;
    private final Class<?> sourceType;
    private final String fieldName;
    private final Map<String, Object> attributes;
    private final long creationTime;
    
    private DictionaryResolutionContext(Builder builder) {
        this.typeCode = builder.typeCode;
        this.rawValue = builder.rawValue;
        this.stringValue = builder.stringValue;
        this.sourceType = builder.sourceType;
        this.fieldName = builder.fieldName;
        this.attributes = new ConcurrentHashMap<>(builder.attributes);
        this.creationTime = System.currentTimeMillis();
    }
    
    public String getTypeCode() {
        return typeCode;
    }
    
    public Object getRawValue() {
        return rawValue;
    }
    
    public String getStringValue() {
        return stringValue;
    }
    
    public Class<?> getSourceType() {
        return sourceType;
    }
    
    public String getFieldName() {
        return fieldName;
    }
    
    public Map<String, Object> getAttributes() {
        return attributes;
    }
    
    public long getCreationTime() {
        return creationTime;
    }
    
    @SuppressWarnings("unchecked")
    public <T> T getAttribute(String key, Class<T> type) {
        Object value = attributes.get(key);
        return type.isInstance(value) ? (T) value : null;
    }
    
    public static Builder builder() {
        return new Builder();
    }
    
    public static class Builder {
        private String typeCode;
        private Object rawValue;
        private String stringValue;
        private Class<?> sourceType;
        private String fieldName;
        private Map<String, Object> attributes = new ConcurrentHashMap<>();
        
        public Builder typeCode(String typeCode) {
            this.typeCode = typeCode;
            return this;
        }
        
        public Builder rawValue(Object rawValue) {
            this.rawValue = rawValue;
            this.stringValue = rawValue == null ? null : rawValue.toString();
            return this;
        }
        
        public Builder sourceType(Class<?> sourceType) {
            this.sourceType = sourceType;
            return this;
        }
        
        public Builder fieldName(String fieldName) {
            this.fieldName = fieldName;
            return this;
        }
        
        public Builder attribute(String key, Object value) {
            this.attributes.put(key, value);
            return this;
        }
        
        public Builder attributes(Map<String, Object> attributes) {
            this.attributes.putAll(attributes);
            return this;
        }
        
        public DictionaryResolutionContext build() {
            return new DictionaryResolutionContext(this);
        }
    }
}
